/* GPIO Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "main.h"
#include "Analog_IIC.h"
#include "lamp_ctrl.h"
#include "generic_gpio.h"
#include "nvs_value.h"
#include "ws2812.h"
#include "mqtt_cjson_handle.h"
#include "h03_config.h"

/**
 * Brief:
 * This test code shows how to configure gpio and how to use gpio interrupt.
 *
 * GPIO status:
 * GPIO18: output (ESP32C2/ESP32H2 uses GPIO8 as the second output pin)
 * GPIO19: output (ESP32C2/ESP32H2 uses GPIO9 as the second output pin)
 * GPIO4:  input, pulled up, interrupt from rising edge and falling edge
 * GPIO5:  input, pulled up, interrupt from rising edge.
 *
 * Note. These are the default GPIO pins to be used in the example. You can
 * change IO pins in menuconfig.
 *
 * Test:
 * Connect GPIO18(8) with GPIO4
 * Connect GPIO19(9) with GPIO5
 * Generate pulses on GPIO18(8)/19(9), that triggers interrupt on GPIO4/5
 *
 */

#define TAG "[TOUCH]"

extern bool IIC_intr;
uint8_t slide_now = 0;
uint8_t key_now = 0;
uint8_t slide_pos = 90;
uint8_t key1_count = 0;
extern bool system_restore_flag;
static QueueHandle_t gpio_evt_queue = NULL;

static void IRAM_ATTR touch_isr_handler(void* arg)
{
    if(system_state.main != OTA){
        uint32_t gpio_num = (uint32_t) arg;
        xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
    }
}

void set_slide_indicator(uint8_t level)
{
    uint8_t slide_led_num;
    uint8_t slide_led_bit = 0;                        
    // slide_led_num = level;
    slide_led_num = level/16 + 1;
    if(slide_led_num <= 7){
        for(uint8_t i=0;i<slide_led_num;i++){
            slide_led_bit |= 0x01<<i;
        }
        ET6226M_write_data(DIS_ADD_1, slide_led_bit);
        ET6226M_write_data(DIS_ADD_2, data_null);
        ET6226M_write_data(DIS_ADD_3, data_null);
    }else if(slide_led_num <= 14){
        slide_led_num -= 7;
        for(uint8_t i=0;i<slide_led_num;i++){
            slide_led_bit |= 0x01<<i;
        }
        ET6226M_write_data(DIS_ADD_1, 0xff);
        ET6226M_write_data(DIS_ADD_2, slide_led_bit);
        ET6226M_write_data(DIS_ADD_3, data_null);
    }else if(slide_led_num > 14){
        slide_led_num -= 14;
        for(uint8_t i=0;i<slide_led_num;i++){
            slide_led_bit |= 0x01<<i;
        }
        ET6226M_write_data(DIS_ADD_1, 0xff);
        ET6226M_write_data(DIS_ADD_2, 0xff);
        ET6226M_write_data(DIS_ADD_3, slide_led_bit);
    }
}

static void set_func_indicator(uint8_t key1, uint8_t scene_mode, uint8_t key5)
{
    uint8_t func_key_bit = 0;
    func_key_bit |= key1;
    if(scene_mode != 0){
        func_key_bit |= (1<<(scene_mode));
    }
    func_key_bit |= (key5<<4);
    ET6226M_write_data(DIS_ADD_4, func_key_bit);
}

void key1_indicator_updata(uint8_t status)
{
    if(lamp.onoff_status == 1){
        set_func_indicator(status, lamp.scene_mode, lamp.tomato_mode);
        set_slide_indicator(lamp.brightness_val);
    }else{
        ET6226M_clean_all();
        set_func_indicator(status, 0, 0);
    }
}

void indicator_updata(void)
{
    if(lamp.onoff_status == 1){
        set_func_indicator(lamp.onoff_status, lamp.scene_mode, lamp.tomato_mode);
        set_slide_indicator(lamp.brightness_val);
    }else{
        ET6226M_clean_all();
    }
}

uint8_t key_password_now[6] = {0};
const uint8_t key_password[6] = {2,4,2,3,5,1};
static uint8_t key_set_password(uint8_t key)
{
    static uint8_t key_i = 0;
    if(key == 2 && event_flag.key_password == 0 && lamp.onoff_status == 0){
        event_flag.key_password = 1;
        timer_count.key_password = 5;
        key_i = 0;
    }
    if(event_flag.key_password){
        key_password_now[key_i] = key;
        key_i++;
        if(key_i == 6){
            key_i = 0;
            event_flag.key_password = 0;
            timer_count.key_password = 0;
            uint8_t correct = 0;
            for(uint8_t i=0;i<6;i++){
                if(key_password_now[i] == key_password[i]){
                    correct++;
                }else{
                    return 1;
                    break;
                }
            }
            if(correct == 6){
                ET6226M_display_all();
                if(device_attr.debug_mode == 0){
                    device_attr.debug_mode = 1;
                    esp_log_level_set("*", ESP_LOG_INFO);
                    led_notify = BLUE_NOTIFICATION;
                }else{
                    device_attr.debug_mode = 0;
                    esp_log_level_set("*", ESP_LOG_ERROR);
                    led_notify = RED_NOTIFICATION;
                }
                event_flag.led_break = 1;
                printf("debug_mode: %d\n", device_attr.debug_mode);
                paramenter_setting_u8("debug_mode", device_attr.debug_mode);
                vTaskDelay(200 / portTICK_PERIOD_MS);
                ET6226M_clean_all();
                return 0;
            }
        }
    }
    return 1;
}

static void touch_change_state(uint8_t key)
{
    bool lamp_updata_flag = 0;
    bool ret = 1;
    ret = key_set_password(key);
    if(lamp.onoff_status == 1){
        switch(key){
            case 0:
                break;
            case 1:
                lamp.onoff_status = 0;
                lamp.tomato_mode = 0;
                lamp_updata_flag = 1;
                break;
            case 2:
                lamp.color_temp = 0;
                lamp.scene_mode = 1;
                break;
            case 3:
                lamp.color_temp = 128;
                lamp.scene_mode = 2;
                break;
            case 4:
                lamp.color_temp = 255;
                lamp.scene_mode = 3;
                break;
            case 5:
                if(lamp.tomato_mode == 1){
                    lamp.tomato_mode = 0;
                }else{
                    lamp.tomato_mode = 1;
                }
                timer_count.led_tomato_clock = 0;
                indicator_updata();
                break;
            default:
                break;
        }
        if(lamp_ex.color_temp != lamp.color_temp){
            lamp_ex.color_temp = lamp.color_temp;
            cJSON_creat_attr("color_temp", lamp.color_temp);
            paramenter_setting_u8("color_temp", lamp.color_temp);
            paramenter_setting_u8("scene_mode", lamp.scene_mode);
            lamp_updata_flag = 1;
        }
    }else if(key == 1 && ret == 1){
        lamp.onoff_status = 1;
        lamp_updata_flag = 1;
        if(top_led_mode == 1){
            top_led_mode = 2;
            event_flag.led_break = 1;
            ESP_LOGI(TAG, "exit system mode show");
        }
    }
    if(lamp_updata_flag == 1){
        lamp_updata(lamp.onoff_status, lamp.brightness_val, lamp.color_temp);
    }
}

uint8_t Read_Buffer[6]; //主控端的读取资料缓存

static void HY16009A_task(void *arg)
{
    uint32_t io_num;
    int button_state = 0;
    bool ACK = 1;
    static bool slide_push_flag = 0;
    uint8_t slide_Buffer_ex = 0;
    uint8_t Calibrating;
    uint8_t wheel;
    static bool press_flag;
    static uint16_t sum,sum_ex;

    for(;;) {
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
            // ESP_LOGI(TAG, "GPIO[%" PRIu32 "] intr, val: %d", io_num, button_state = gpio_get_level(io_num));
            if(button_state == 0){
                press_flag = 1;
                while(press_flag){
                    ACK = touchboard_read_data(HY16009A_addr_R, Read_Buffer, 2); //读取按键状态
                    if(ACK == 0){
                        Calibrating = Read_Buffer[0] & 0x80;
                        if(Calibrating == 0x80){
                            sum = Read_Buffer[0] + Read_Buffer[1];
                            if(sum != sum_ex){
                                sum_ex = sum;
                                // printf_buf("->", Read_Buffer, 2);
                                wheel = Read_Buffer[0] & 0x10;
                                if(wheel == 0x00){
                                    if(slide_push_flag == 1){
                                        slide_push_flag = 0;
                                        lamp.brightness_val = slide_pos;
                                        if(lamp_ex.brightness_val != lamp.brightness_val){
                                            lamp_ex.brightness_val = lamp.brightness_val;
                                            cJSON_creat_attr("brightness_val", lamp.brightness_val);
                                            paramenter_setting_u8("brightness_val", lamp.brightness_val);
                                        }
                                    }
                                    if(Read_Buffer[0] == 0x80){ /*放手*/
                                        press_flag = 0;
                                        key1_count = 0;
                                        key_now = 0;
                                        if(system_restore_flag == 1){
                                            paramenter_restore(2);
                                            restart_os();
                                        }
                                    }else{ /*按下*/
                                        for(uint8_t i=0;i<6;i++){
                                            key_now = (Read_Buffer[0] >>i)&0x01;
                                            if(key_now == 1){
                                                switch(i){
                                                    case 0:
                                                        key_now = 4;
                                                        break;
                                                    case 1:
                                                        key_now = 5;
                                                        break;
                                                    case 2:
                                                        key_now = 1;
                                                        break;
                                                    case 3:
                                                        key_now = 2;
                                                        break;
                                                    case 5:
                                                        key_now = 3;
                                                        break;
                                                    default:
                                                        break;
                                                }
                                                break;
                                            }
                                        }
                                        touch_change_state(key_now);
                                    }
                                    ESP_LOGD(TAG, "touch key: %d", key_now);
                                }else{
                                    slide_push_flag = 1;
                                    if(lamp.onoff_status == 1){
                                        if(Read_Buffer[1] < 12){
                                            Read_Buffer[1] = 12;
                                        }else if(Read_Buffer[1] > 180){
                                            Read_Buffer[1] = 180;
                                        }
                                        if(Read_Buffer[1] != slide_Buffer_ex){
                                            slide_Buffer_ex = Read_Buffer[1];
                                            slide_pos = 192-Read_Buffer[1];
                                            slide_pos = (slide_pos-12)*255/168;
                                            if(slide_pos == 0){
                                                slide_pos = 1;
                                            }
                                            lamp.brightness_val = slide_pos;
                                            set_slide_indicator(lamp.brightness_val);
                                            lamp_set_fade(lamp.brightness_val, lamp.color_temp, 50);
                                            ESP_LOGD(TAG, "slide_pos: %d", slide_pos);
                                        }
                                    }
                                }
                            }
                        }else{
                            ESP_LOGE(TAG, "HY16009A is not ready");
                        }
                    }
                    vTaskDelay(10 / portTICK_PERIOD_MS);
                }
            }
        }
    }
}

static void TTY6955_task(void *arg)
{
    uint32_t io_num;
    // int button_state = 0;
    bool ACK = 1;
    static bool slide_push_flag = 0;
    uint8_t key_Buffer_ex = 0;
    uint8_t slide_Buffer_ex = 0;

    for(;;) {
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
            // ESP_LOGI(TAG, "GPIO[%" PRIu32 "] intr, val: %d", io_num, button_state = gpio_get_level(io_num));
            ACK = touchboard_read_data(TTY6955_addr_R, Read_Buffer, 6); //读取按键状态
            if(ACK == 0){
                // printf_buf("->", Read_Buffer, 6);
                uint8_t Calibrating,WSET;
                Calibrating = Read_Buffer[0] & 0x80;
                WSET = Read_Buffer[0] & 0x40;
                if(Calibrating == 0 || WSET != 0){
                    ESP_LOGE(TAG, "reset TTY6955!!!");
                    TTY6955_write_setting();
                    vTaskDelay(50 / portTICK_PERIOD_MS);
                }else{
                    if(Read_Buffer[0] == 0x80){
                        if(slide_push_flag == 1){
                            slide_push_flag = 0;
                            lamp.brightness_val = slide_pos;
                            if(lamp_ex.brightness_val != lamp.brightness_val){
                                lamp_ex.brightness_val = lamp.brightness_val;
                                cJSON_creat_attr("brightness_val", lamp.brightness_val);
                                paramenter_setting_u8("brightness_val", lamp.brightness_val);
                            }
                        }
                        if(Read_Buffer[1] != key_Buffer_ex){
                            key_Buffer_ex = Read_Buffer[1];
                            if(Read_Buffer[1] == 0){
                                key1_count = 0;
                                key_now = 0;
                                if(system_restore_flag == 1){
                                    paramenter_restore(2);
                                    restart_os();
                                }
                            }else{
                                for(uint8_t i=0;i<5;i++){
                                    key_now = (Read_Buffer[1] >>i)&0x01;
                                    if(key_now == 1){
                                        key_now = i+1;
                                        break;
                                    }
                                }
                                touch_change_state(key_now);
                            }
                            ESP_LOGD(TAG, "touch key: %d", key_now);
                        }
                    }else if(Read_Buffer[0] == 0x82){
                        slide_push_flag = 1;
                        if(lamp.onoff_status == 1 && Read_Buffer[1] == 0x00 && Read_Buffer[4] != 0x0 && Read_Buffer[4] != 224){
                            if(Read_Buffer[4] < 14){
                                Read_Buffer[4] = 14;
                            }else if(Read_Buffer[4] > 209){
                                Read_Buffer[4] = 209;
                            }
                            if(Read_Buffer[4] != slide_Buffer_ex){
                                slide_Buffer_ex = Read_Buffer[4];
                                slide_pos = 224-Read_Buffer[4];
                                slide_pos = (slide_pos-14)*255/196;
                                set_slide_indicator(slide_pos);
                                lamp_set_fade(slide_pos, lamp.color_temp, 50);
                                ESP_LOGD(TAG, "slide_pos: %d", slide_pos);
                            }
                        }
                    }
                }
            }
        }
    }
}

void touch_board_init(void)
{
    //create a queue to handle gpio event from isr
    gpio_evt_queue = xQueueCreate(5, sizeof(uint32_t));

    //install gpio isr service
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    //hook isr handler for specific gpio pin
    gpio_isr_handler_add(TOUCH_INT, touch_isr_handler, (void*) TOUCH_INT);
    
    ET6226M_Init();

    if(device_attr.silent_ota == 0){
        lamp_set_brightness(0, lamp.color_temp);
    }else{
        indicator_updata();
        device_attr.silent_ota = 0;
        paramenter_setting_u8("s_ota", 0);
    }
    if(user_attr.touch_mode == 0){
        TTY6955_write_setting();
        vTaskDelay(50 / portTICK_PERIOD_MS);
        xTaskCreate(TTY6955_task, "TTY6955_task", 1024*4, NULL, 14, NULL);
    }else{
        xTaskCreate(HY16009A_task, "HY16009A_task", 1024*4, NULL, 14, NULL);
    }
}
